package transport;

import java.io.IOException;
import java.net.Socket;
import java.util.*;

/**
 * UniProtocol class provides pipe-based messaging protocol.
 */
public final class UniProtocol extends Protocol {
    public static final class BindInfo {
        public final UniClient client;
        public final String queueMask;

        public BindInfo(String queueMask, UniClient client) {
            this.queueMask = queueMask;
            this.client = client;
        }

        public boolean doesSupportName(String name) {
            // TODO: support wildcards
            return queueMask.equals(name);
        }
    }

    private final List<BindInfo> binds = new LinkedList<BindInfo>();
    private final Map<String, UniClient[]> queueClientsCache = new HashMap<String, UniClient[]>();

    public synchronized UniClient [] getQueueClients(String name) {
        if (queueClientsCache.containsKey(name)) {
            return queueClientsCache.get(name);
        }

        ArrayList<UniClient> res = new ArrayList<UniClient>(binds.size());

        for (BindInfo info : binds) {
            if (info.doesSupportName(name)) {
                res.add(info.client);
            }
        }

        UniClient [] resArray = res.toArray(new UniClient[res.size()]);

        queueClientsCache.put(name, resArray);

        return resArray;
    }

    public synchronized void bindQueue(String queueMask, UniClient client) {
        for (BindInfo info : binds) {
            if (info.queueMask.equals(queueMask) && info.client == client) {
                return ;
            }
        }

        binds.add(new BindInfo(queueMask, client));

        queueClientsCache.clear();
    }

    @Override
    public ProtocolAgent createProtocolAgent(Socket socket) throws IOException {
        return new UniProtocolAgent(this, socket);
    }
}
